package top.codecrab.prodConsumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 生产者-消费者-传统模式
 *
 * @author codecrab
 * @since 2021年07月01日 10:44
 */
public class TraditionDemo {
    public static void main(String[] args) {
        Home home = new Home();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                home.play();
            }
        }, "小明").start();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                home.rest();
            }
        }, "小红").start();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                home.play();
            }
        }, "小亮").start();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                home.rest();
            }
        }, "小绿").start();
    }
}

/**
 * 资源类，家庭
 */
class Home {

    private final Lock lock = new ReentrantLock();

    private final Condition condition = lock.newCondition();

    /**
     * 正在玩电脑的人数
     */
    private int playing = 0;

    /**
     * 没有人玩的时候，才能被其他人玩，也就是等于0的时候
     */
    private final int noOne = 0;

    /**
     * 玩电脑
     */
    public void play() {
        lock.lock();
        try {
            while (playing != noOne) {
                //已经有人在玩电脑了，就等待
                condition.await();
            }
            //玩电脑中的人数加一
            playing++;
            System.out.println("正在玩电脑的人数：" + playing);
            //加一后，唤醒其他线程
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 休息
     */
    public void rest() {
        lock.lock();
        try {
            while (playing == noOne) {
                //没有玩的人，那就没法休息，就先等待
                condition.await();
            }
            //有玩的人，就去休息
            playing--;
            System.out.println("正在玩电脑的人数：" + playing);
            //唤醒其他线程，告诉他们有位置了
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
